package org.zoomdev.zoom.ioc.impl.factories;

import org.zoomdev.zoom.common.exceptions.ZoomException;
import org.zoomdev.zoom.ioc.IocConstructor;
import org.zoomdev.zoom.ioc.IocFactory;
import org.zoomdev.zoom.ioc.IocKey;
import org.zoomdev.zoom.ioc.IocTypeKey;

import java.util.Collection;
import java.util.Collections;

public final class InterfaceIocFactory implements IocFactory, IocFactory.IocKeyContainer {

    private final ClassIocFactory factory;

    public InterfaceIocFactory(ClassIocFactory factory) {
        this.factory = factory;
    }


    @Override
    public IocConstructor createConstructor(IocKey key) {
        if (key.getType() == null) {
            return null;
        }
        if (isInterface(key)) {
            //查找实现类
            Class<?> type = (Class<?>) key.getType();
            String name = type.getSimpleName();
            String packageName = type.getPackage().getName();

            String impl = packageName + ".impl." + name + "Impl";
            try {
                Class<?> implType = Class.forName(impl);
                Class interfaceType = (Class) key.getType();
                if (!interfaceType.isAssignableFrom(implType)) {
                    throw new ZoomException("接口的实现类 " + impl + " 没有实现接口:" + type);
                }
                key = new IocTypeKey(implType);
            } catch (ClassNotFoundException e) {
                return null;
            }
        }
        return factory.create0(key);
    }

    @Override
    public Collection<IocKey> find(Class type) {
        String className = type.getName();
        if (className.endsWith("Impl")) {
            String interfaceName = className.substring(0, className.length() - 4);
            int dotPos = interfaceName.lastIndexOf('.');
            if (dotPos > 0) {
                String name = interfaceName.substring(dotPos + 1);
                String packageName = interfaceName.substring(0, dotPos);
                dotPos = packageName.lastIndexOf('.');
                packageName = packageName.substring(0, dotPos);
                try {
                    Class interfaceClass = Class.forName(packageName + "." + name, false, getClass().getClassLoader());
                    if (interfaceClass.isAssignableFrom(type)) {
                        return Collections.singletonList(new IocTypeKey(interfaceClass));
                    }
                } catch (ClassNotFoundException e) {

                }
            }

        }
        return null;
    }

    private boolean isInterface(IocKey key) {
        if (key.getType() instanceof Class) {
            return ((Class<?>) key.getType()).isInterface();
        }
        return false;
    }
}
